import {
    updateNodeElement
} from "../dom"
import {
    arrayfy,
    createStateNode,
    createTaskQue,
    getRoot,
    getTag
} from "../utils"
let subTask = null

const queue = createTaskQue()
let pendingCommit = null

function performTask(deadline) {
    workLoop(deadline)
    if (subTask && !queue.isEmpty()) {
        requestIdleCallback(performTask)
    }
}

function commitAllWork(fiber) {
    fiber.effects.forEach(item => {
        if (item.tag === 'class_component') {
            item.stateNode.__fiber = item
        }
        if (item.effactTag === 'placement') {
            let parentFiber = item.parent
            while (parentFiber.tag === 'class_component' || parentFiber.tag === 'function_component') {
                parentFiber = parentFiber.parent
            }
            if (item.tag === 'host_component') {
                parentFiber.stateNode.appendChild(item.stateNode)
            }
        } else if (item.effactTag === 'update') {
            // 更新
            if (item.type === item.alternate.type) {
                updateNodeElement(item.stateNode, item, item.alternate)
            } else {
                // 节点类型不同
                item.parent.stateNode.replaceChild(item.stateNode, item.alternate.stateNode)
            }
        } else if (item.effactTag === 'delete') {
            item.parent.stateNode.removeChild(item.stateNode)
        }
    })
    // 保存fiber对象
    fiber.stateNode.__rootFiberContainer = fiber
}

function getFirstTask() {
    const task = queue.pop()
    if (task.from === 'class_component') {
        const root = getRoot(task.instance)
        task.instance.__fiber.partialState = task.partialState
        return {
            props: root.props,
            stateNode: root.stateNode,
            tag: 'host_root',
            effects: [],
            child: null,
            alternate: root
        }
    }
    return {
        props: task.props,
        stateNode: task.el,
        tag: 'host_root',
        effects: [],
        child: null,
        alternate: task.el.__rootFiberContainer
    }
}

function reconcileChildren(fiber, children) {
    // children变成数组
    let arrayfiedChildren = arrayfy(children)
    let i = 0
    let numberOfElements = arrayfiedChildren.length
    let element = null
    let prevFiber = null
    let alternate = null
    if (fiber.alternate && fiber.alternate.child) {
        alternate = fiber.alternate.child
    }

    while (i < numberOfElements || alternate) {
        element = arrayfiedChildren[i]
        let newFiber
        if (!element && alternate) {
            alternate.effactTag = 'delete'
            fiber.effects.push(alternate)
        } else if (element && !alternate) {
            newFiber = {
                type: element.type,
                props: element.props,
                tag: getTag(element),
                effects: [],
                effactTag: 'placement',
                stateNode: null,
                parent: fiber
            }
            newFiber.stateNode = createStateNode(newFiber)

        } else if (element && alternate) {
            newFiber = {
                type: element.type,
                props: element.props,
                tag: getTag(element),
                effects: [],
                effactTag: 'update',
                stateNode: null,
                parent: fiber,
                alternate
            }
            if (element.type === alternate.type) {
                newFiber.stateNode = alternate.stateNode
            } else {
                newFiber.stateNode = createStateNode(newFiber)
            }
        }
        if (i === 0) {
            fiber.child = newFiber
        } else if (element) {
            prevFiber.sibling = newFiber
        }

        console.log(alternate)
        if (alternate && alternate.sibling) {
            alternate = alternate.sibling
        } else {

            alternate = null
        }
        prevFiber = newFiber
        i++
    }
}



function excuteTask(fiber) {
    if (fiber.tag === 'class_component') {
        if (fiber.stateNode.__fiber && fiber.stateNode.__fiber.partialState) {
            fiber.stateNode.state = {
                ...fiber.stateNode.state,
                ...fiber.stateNode.__fiber.partialState
            }
        }
        reconcileChildren(fiber, fiber.stateNode.render())
    } else if (fiber.tag === 'function_component') {
        reconcileChildren(fiber, fiber.stateNode(fiber.props))
    } else {
        reconcileChildren(fiber, fiber.props.children)
    }
    if (fiber.child) {
        return fiber.child
    }
    while (fiber.parent) {
        fiber.parent.effects = fiber.parent.effects.concat(fiber.effects.concat([fiber]))
        if (fiber.sibling) {
            return fiber.sibling
        }
        fiber = fiber.parent
    }
    pendingCommit = fiber
}

function workLoop(deadline) {
    // 构建最外层节点
    if (!subTask) {
        subTask = getFirstTask()
    }
    console.log(subTask)
    //  && deadline.timeRemaining() > 1
    while (subTask) {
        subTask = excuteTask(subTask)
    }
    if (pendingCommit) {
        commitAllWork(pendingCommit)
    }
}

export function render(virtualDOM, el) {
    queue.push({
        el,
        props: {
            children: virtualDOM
        }
    })
    requestIdleCallback(performTask)
}

export function scheduleUpdate(instance, partialState) {
    console.log(partialState)
    queue.push({
        from: 'class_component',
        instance,
        partialState
    })
    requestIdleCallback(performTask)
}